/*
 * MIT License
 *
 * Copyright (c) 2023-present, tangli
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package tony.test.mybatis.datascope.unit

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import tony.mybatis.datascope.IDataScopeContext
import tony.mybatis.datascope.model.ScopedColumn
import tony.mybatis.datascope.model.ScopedTable
import tony.mybatis.datascope.model.TableNameType
import tony.test.mybatis.datascope.DataScopeBaseTest

/**
 * 数据权限配置API正确性测试
 * @author tangli
 * @date 2025/09/21 10:00
 */
@DisplayName("数据权限配置API正确性测试")
class DataScopeTest : DataScopeBaseTest() {

    @Autowired
    private lateinit var dataScopeContext: IDataScopeContext

    @Nested
    @DisplayName("用户ID配置正确性验证")
    inner class UserIdConfigurationTest {

        @Test
        @DisplayName("userIdList():替换用户ID列表正确性")
        fun testUserIdListReplacementCorrectness() {
            var executionCount = 0

            // 初始设置
            val dataScope = dataScopeContext.dataScope()
                .userIdList(listOf("user1", "user2"))

            dataScope.call {
                executionCount++
                logger.info("=== userIdList替换测试第{}次执行 ===", executionCount)
                "test_result_1"
            }

            // 替换用户ID列表
            dataScope.userIdList(listOf("user3", "user4"))

            dataScope.call {
                executionCount++
                logger.info("=== userIdList替换测试第{}次执行 ===", executionCount)
                "test_result_2"
            }

            assertEquals(2, executionCount)
            logger.info("用户ID列表替换功能验证完成")
        }

        @Test
        @DisplayName("includeUserId():增加用户ID正确性")
        fun testIncludeUserIdCorrectness() {
            val dataScope = dataScopeContext.dataScope()
                .userIdList(listOf("user1"))
                .includeUserId("user2", "user3")

            val result = dataScope.call {
                logger.info("=== includeUserId功能测试 ===")
                "include_test_result"
            }

            assertEquals("include_test_result", result)
            logger.info("增加用户ID功能验证完成")
        }

        @Test
        @DisplayName("includeUserIdList():批量增加用户ID正确性")
        fun testIncludeUserIdListCorrectness() {
            val dataScope = dataScopeContext.dataScope()
                .userIdList(listOf("user1"))
                .includeUserIdList(listOf("user4", "user5"))

            val result = dataScope.call {
                logger.info("=== includeUserIdList功能测试 ===")
                "batch_include_test_result"
            }

            assertEquals("batch_include_test_result", result)
            logger.info("批量增加用户ID功能验证完成")
        }
    }

    @Nested
    @DisplayName("组织ID配置正确性验证")
    inner class OrgIdConfigurationTest {

        @Test
        @DisplayName("orgIdList():替换组织ID列表正确性")
        fun testOrgIdListReplacementCorrectness() {
            val dataScope = dataScopeContext.dataScope()
                .orgIdList(listOf("org1", "org2"))

            val result = dataScope.call {
                logger.info("=== orgIdList功能测试 ===")
                "org_test_result"
            }

            assertEquals("org_test_result", result)
            logger.info("组织ID列表设置功能验证完成")
        }

        @Test
        @DisplayName("includeOrgId():增加组织ID正确性")
        fun testIncludeOrgIdCorrectness() {
            val dataScope = dataScopeContext.dataScope()
                .orgIdList(listOf("org1"))
                .includeOrgId("org2", "org3")

            val result = dataScope.call {
                logger.info("=== includeOrgId功能测试 ===")
                "include_org_test_result"
            }

            assertEquals("include_org_test_result", result)
            logger.info("增加组织ID功能验证完成")
        }

        @Test
        @DisplayName("includeOrgIdList():批量增加组织ID正确性")
        fun testIncludeOrgIdListCorrectness() {
            val dataScope = dataScopeContext.dataScope()
                .orgIdList(listOf("org1"))
                .includeOrgIdList(listOf("org4", "org5"))

            val result = dataScope.call {
                logger.info("=== includeOrgIdList功能测试 ===")
                "batch_include_org_test_result"
            }

            assertEquals("batch_include_org_test_result", result)
            logger.info("批量增加组织ID功能验证完成")
        }
    }

    @Nested
    @DisplayName("列名配置正确性验证")
    inner class ColumnConfigurationTest {

        @Test
        @DisplayName("userIdColumn():设置用户ID列名正确性")
        fun testUserIdColumnCorrectness() {
            val dataScope = dataScopeContext.dataScope()
                .userIdColumn("custom_user_id")
                .userIdList(listOf("user1"))

            val result = dataScope.call {
                logger.info("=== userIdColumn功能测试 ===")
                "user_column_test_result"
            }

            assertEquals("user_column_test_result", result)
            logger.info("用户ID列名设置功能验证完成")
        }

        @Test
        @DisplayName("orgIdColumn():设置组织ID列名正确性")
        fun testOrgIdColumnCorrectness() {
            val dataScope = dataScopeContext.dataScope()
                .orgIdColumn("custom_org_id")
                .orgIdList(listOf("org1"))

            val result = dataScope.call {
                logger.info("=== orgIdColumn功能测试 ===")
                "org_column_test_result"
            }

            assertEquals("org_column_test_result", result)
            logger.info("组织ID列名设置功能验证完成")
        }
    }

    @Nested
    @DisplayName("表过滤配置正确性验证")
    inner class TableFilterConfigurationTest {

        @Test
        @DisplayName("excludeTables():排除表配置正确性")
        fun testExcludeTablesCorrectness() {
            val tables = listOf(
                ScopedTable("sys_dict", TableNameType.TABLE),
                ScopedTable("d", TableNameType.ALIAS)
            )

            val dataScope = dataScopeContext.dataScope()
                .userIdList(listOf("user1"))
                .excludeTables(tables)

            val result = dataScope.call {
                logger.info("=== excludeTables功能测试 ===")
                "exclude_tables_test_result"
            }

            assertEquals("exclude_tables_test_result", result)
            logger.info("排除表配置功能验证完成")
        }

        @Test
        @DisplayName("excludeTableNames():排除表名配置正确性")
        fun testExcludeTableNamesCorrectness() {
            val dataScope = dataScopeContext.dataScope()
                .userIdList(listOf("user1"))
                .excludeTableNames(listOf("sys_dict", "sys_user"))

            val result = dataScope.call {
                logger.info("=== excludeTableNames功能测试 ===")
                "exclude_table_names_test_result"
            }

            assertEquals("exclude_table_names_test_result", result)
            logger.info("排除表名配置功能验证完成")
        }

        @Test
        @DisplayName("includeTables():包含表配置正确性")
        fun testIncludeTablesCorrectness() {
            val tables = listOf(
                ScopedTable("sys_dict", TableNameType.TABLE),
                ScopedTable("sys_user", TableNameType.TABLE)
            )

            val dataScope = dataScopeContext.dataScope()
                .userIdList(listOf("user1"))
                .includeTables(tables)

            val result = dataScope.call {
                logger.info("=== includeTables功能测试 ===")
                "include_tables_test_result"
            }

            assertEquals("include_tables_test_result", result)
            logger.info("包含表配置功能验证完成")
        }

        @Test
        @DisplayName("includeTableNames():包含表名配置正确性")
        fun testIncludeTableNamesCorrectness() {
            val dataScope = dataScopeContext.dataScope()
                .userIdList(listOf("user1"))
                .includeTableNames(listOf("sys_dict"))

            val result = dataScope.call {
                logger.info("=== includeTableNames功能测试 ===")
                "include_table_names_test_result"
            }

            assertEquals("include_table_names_test_result", result)
            logger.info("包含表名配置功能验证完成")
        }
    }

    @Nested
    @DisplayName("自定义列映射配置正确性验证")
    inner class ScopedColumnConfigurationTest {

        @Test
        @DisplayName("scopedColumns():自定义列映射配置正确性")
        fun testScopedColumnsCorrectness() {
            val scopedColumns = listOf(
                ScopedColumn("d", "custom_user_id", "custom_org_id"),
                ScopedColumn("u", "user_creator_id", "user_org_id")
            )

            val dataScope = dataScopeContext.dataScope()
                .userIdList(listOf("user1"))
                .orgIdList(listOf("org1"))
                .scopedColumns(scopedColumns)

            val result = dataScope.call {
                logger.info("=== scopedColumns功能测试 ===")
                "scoped_columns_test_result"
            }

            assertEquals("scoped_columns_test_result", result)
            logger.info("自定义列映射配置功能验证完成")
        }
    }

    @Nested
    @DisplayName("链式调用正确性验证")
    inner class ChainCallCorrectnessTest {

        @Test
        @DisplayName("复杂链式调用:所有配置组合正确性")
        fun testComplexChainCallCorrectness() {
            val scopedColumns = listOf(
                ScopedColumn("d", "dict_user_id", "dict_org_id")
            )

            val dataScope = dataScopeContext.dataScope()
                .userIdList(listOf("user1"))
                .includeUserId("user2", "user3")
                .orgIdList(listOf("org1"))
                .includeOrgId("org2")
                .userIdColumn("custom_user_id")
                .orgIdColumn("custom_org_id")
                .includeTableNames(listOf("sys_dict", "sys_user"))
                .scopedColumns(scopedColumns)

            val result = dataScope.call {
                logger.info("=== 复杂链式调用功能测试 ===")
                "complex_chain_test_result"
            }

            assertEquals("complex_chain_test_result", result)
            logger.info("复杂链式调用功能验证完成")
        }

        @Test
        @DisplayName("多次call调用:配置保持正确性")
        fun testMultipleCallCorrectness() {
            val dataScope = dataScopeContext.dataScope()
                .userIdList(listOf("user1"))
                .orgIdList(listOf("org1"))

            // 第一次调用
            val result1 = dataScope.call {
                logger.info("=== 第一次call调用 ===")
                "first_call_result"
            }

            // 第二次调用，配置应该保持
            val result2 = dataScope.call {
                logger.info("=== 第二次call调用 ===")
                "second_call_result"
            }

            assertEquals("first_call_result", result1)
            assertEquals("second_call_result", result2)
            logger.info("多次call调用配置保持验证完成")
        }

        @Test
        @DisplayName("run方法:无返回值执行正确性")
        fun testRunMethodCorrectness() {
            var executed = false

            dataScopeContext.dataScope()
                .userIdList(listOf("user1"))
                .run {
                    logger.info("=== run方法执行测试 ===")
                    executed = true
                }

            assertTrue(executed)
            logger.info("run方法执行功能验证完成")
        }
    }
}
